package org.web.accesscontrollist.sdk.helper;

import org.web.accesscontrollist.sdk.dto.AclResourceDetailDTO;
import org.web.accesscontrollist.sdk.dto.AclResourceUserBindingDTO;
import org.web.accesscontrollist.sdk.dto.constant.ResourceLevel;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class TreeHelper {

    public static final String SEPARATOR = "-";

    /**
     * buildLevelTreeMap 方法执行了一个转换操作，将给定的 List<AclResourceUserBindingDTO> 转换成了一个多层级的 Map 数据结构。
     * 这个数据结构的键是整数，代表资源级别，
     * 值是另一个 Map，其键是由资源路径构成的字符串，值是 AclResourceUserBindingDTO 实例。
     * */
    public static Map<Integer, Map<String, AclResourceDetailDTO>> buildlevelTreeMap(List<AclResourceDetailDTO> detailDTOList, String separator) {
        Map<Integer, Map<String, AclResourceDetailDTO>> levelTreeMap = new HashMap<>();
        for (AclResourceDetailDTO detail : detailDTOList) {
            // 第一层级, 从第二级开始，原因是第一级标识的特别信息，比如角色、分组等。
            if (detail.getResourceLevel() == ResourceLevel.FIRST_LEVEL.getLevel()) {
                continue;
            } else if (detail.getResourceLevel() == ResourceLevel.SECOND_LEVEL.getLevel()) {
                Map<String, AclResourceDetailDTO> firstLevelMap = levelTreeMap.computeIfAbsent(ResourceLevel.SECOND_LEVEL.getLevel(), k -> new HashMap<>());
                firstLevelMap.putIfAbsent(buildKey(separator, detail.getSecondLevel()), detail);
            } else if (detail.getResourceLevel() == ResourceLevel.THIRD_LEVEL.getLevel()) {
                Map<String, AclResourceDetailDTO> secondLevelMap = levelTreeMap.computeIfAbsent(ResourceLevel.THIRD_LEVEL.getLevel(), k -> new HashMap<>());
                secondLevelMap.putIfAbsent(buildKey(separator, detail.getSecondLevel(), detail.getThirdLevel()), detail);
            } else if (detail.getResourceLevel() == ResourceLevel.FOURTH_LEVEL.getLevel()) {
                Map<String, AclResourceDetailDTO> thirdLevelMap = levelTreeMap.computeIfAbsent(ResourceLevel.FOURTH_LEVEL.getLevel(), k -> new HashMap<>());
                thirdLevelMap.putIfAbsent(buildKey(separator, detail.getSecondLevel(), detail.getThirdLevel(), detail.getFourthLevel()), detail);
            } else if (detail.getResourceLevel() == ResourceLevel.FIFTH_LEVEL.getLevel()) {
                Map<String, AclResourceDetailDTO> fouthLevelMap = levelTreeMap.computeIfAbsent(ResourceLevel.FIFTH_LEVEL.getLevel(), k -> new HashMap<>());
                fouthLevelMap.putIfAbsent(buildKey(separator, detail.getSecondLevel(), detail.getThirdLevel(), detail.getFourthLevel(), detail.getFifthLevel()), detail);
            } else {
                throw new IllegalArgumentException("Unsupported resource level: " + detail.getResourceLevel());
            }
        }
        return levelTreeMap;
    }

    public static String buildKey(String separator, String... levels) {
        StringBuilder keyBuilder = new StringBuilder();
        for (String level : levels) {
            keyBuilder.append(level);
            keyBuilder.append(separator);
        }
        return keyBuilder.toString();
    }

    public static List<String> buildListByKeyWithSeparator(String key, String separator) {
        List<String> listWithSeparator = new ArrayList<>();
        String[] levels = key.split(separator);
        StringBuilder levelBuilder = new StringBuilder();
        for (String level : levels) {
            levelBuilder.append(level);
            listWithSeparator.add(levelBuilder.toString());
        }
        return listWithSeparator;
    }

    public static AclResourceDetailDTO judgePrivilege(String key, Map<Integer, Map<String, AclResourceDetailDTO>> levelTreeMap, String separator) {
        List<String> listWithoutSeparator = buildListByKeyWithSeparator(key, separator);
        for (int i = 0; i < listWithoutSeparator.size(); i++) {
            int level = i + 1;
            Map<String, AclResourceDetailDTO> levelMap = levelTreeMap.get(level);
            if (levelMap == null) {
                continue;
            }
            AclResourceDetailDTO detailDTO = levelMap.get(listWithoutSeparator.get(i));
            if (detailDTO != null) {
                return detailDTO;
            }
        }
        return null;
    }
}
